package org.jason.article.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jason.article.mapper.CaArticleMapper;
import org.jason.article.mq.producer.ArticleProducer;
import org.jason.article.repository.ArticleContentRepository;
import org.jason.article.service.ICaArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jason.article.service.ICaBlockService;
import org.jason.common.constants.ArticleConstants;
import org.jason.common.constants.ArticleInteractionConstants;
import org.jason.common.redis.RedisCache;
import org.jason.feign.user.UserClient;
import org.jason.model.article.dtos.ExamineDto;
import org.jason.model.interaction.dtos.ArticleInteractionDto;
import org.jason.model.article.dtos.ContributeDto;
import org.jason.model.article.dtos.GetArticlesDto;
import org.jason.model.article.es.ArticleContent;
import org.jason.model.article.pojos.CaArticle;
import org.jason.model.article.pojos.CaBlock;
import org.jason.model.common.dtos.ResponseResult;
import org.jason.model.common.enums.HttpCodeEnum;
import org.jason.model.user.pojos.CuUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 文章详情表 服务实现类
 * </p>
 *
 * @author jason
 * @since 2023-07-23
 */
@Service
@Transactional
public class CaArticleServiceImpl extends ServiceImpl<CaArticleMapper, CaArticle> implements ICaArticleService {

    @Autowired
    private ArticleContentRepository articleContentRepository;

    @Autowired
    private UserClient userClient;

    @Autowired
    private ICaBlockService blockService;

    @Autowired
    private ArticleProducer articleProducer;

    @Autowired
    private RedisCache redisCache;

    /**
     * 获取文章 默认取推荐的10条数据
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getArticles(GetArticlesDto dto) {
        List<CaArticle> articles;
        if (dto.getQueryType() == 0) {
            articles = getRecommendArticles(dto.getBlockId());
        } else {
            articles = getLatestArticles(dto.getBlockId(), dto.getPage());
        }
        if (articles.isEmpty()) {
            return ResponseResult.get(HttpCodeEnum.DATA_NOT_EXIST);
        }
        return new ResponseResult<>(HttpCodeEnum.SUCCESS, articles);
    }

    /**
     * 投稿文章
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult contribute(ContributeDto dto) {
        //设置登录用户id
        int userId = StpUtil.getLoginIdAsInt();
        dto.setUserId(userId);
        //添加到投稿队列
        articleProducer.contributeQueue(dto);
        return ResponseResult.get(HttpCodeEnum.SUCCESS);
    }

    /**
     * 保存文章
     *
     * @param dto
     */
    @Override
    public void saveArticle(ContributeDto dto) {
        int userId = dto.getUserId();
        CuUser user = userClient.getUserInfo(userId).getData();
        CaBlock block = blockService.getById(dto.getBlockId());
        //裁剪文章正文获得文章简介
        String articleContent = dto.getContent();
        String description = articleContent.substring(0, Math.min(articleContent.length(), 140));
        //保存文章
        CaArticle article = new CaArticle()
                .setTitle(dto.getTitle())
                .setDescription(description)
                .setAuthorId(userId)
                .setAuthorNickname(user.getNickname())
                .setBlockId(block.getId())
                .setBlockName(block.getName())
                .setTag(block.getName() + "," + dto.getTag())
                .setCreatedTime(LocalDateTime.now())
                //TODO 审核模块开发完成后改回待审核状态
                .setStatus(ArticleConstants.Pass_The_examination);
        if (StringUtils.isNotBlank(dto.getCoverUrl())) {
            article.setCoverUrl(dto.getCoverUrl());
        }
        this.save(article);
        ArticleContent content = new ArticleContent()
                .setId(article.getId())
                .setTitle(dto.getTitle())
                .setContent(dto.getContent())
                .setAuthorId(userId)
                .setAuthorNickname(user.getNickname())
                .setTag(block.getName() + "," + dto.getTag());
        articleContentRepository.save(content);
    }

    /**
     * 根据用户id获取文章列表
     *
     * @param userId
     * @return
     */
    @Override
    public ResponseResult<List<CaArticle>> getArticlesByUserId(Integer userId) {
        List<CaArticle> articles = this.list(Wrappers.<CaArticle>lambdaQuery()
                .eq(CaArticle::getAuthorId, userId));
        if (articles.isEmpty()) {
            return new ResponseResult<>(HttpCodeEnum.DATA_NOT_EXIST);
        }
        return new ResponseResult<>(HttpCodeEnum.SUCCESS, articles);
    }

    /**
     * 获取待审核文章列表
     *
     * @return 待审核文章列表
     */
    @Override
    public ResponseResult<List<CaArticle>> getToBeExamineArticle() {
        List<CaArticle> articles = this.list(Wrappers.<CaArticle>lambdaQuery()
                .eq(CaArticle::getStatus, ArticleConstants.To_Be_Reviewed));
        if (articles.isEmpty()) {
            return new ResponseResult<>(HttpCodeEnum.DATA_NOT_EXIST);
        }
        return new ResponseResult<>(HttpCodeEnum.SUCCESS, articles);
    }

    /**
     * 审核文章
     *
     * @param dto 审核文章参数
     * @return 结果
     */
    @Override
    public ResponseResult examineArticle(ExamineDto dto) {
        CaArticle article = this.getById(dto.getArticleId());
        if (article == null) {
            return new ResponseResult<>(HttpCodeEnum.DATA_NOT_EXIST);
        }
        if (dto.getStatus() == 0) {
            this.updateById(article.setStatus(ArticleConstants.Pass_The_examination));
        } else if (dto.getStatus() == 1) {
            this.updateById(article.setStatus(ArticleConstants.Returned));
        }
        return ResponseResult.get(HttpCodeEnum.SUCCESS);
    }

    /**
     * 根据id获取文章内容
     *
     * @param articleId
     * @return
     */
    @Override
    public ResponseResult<ArticleContent> getArticleContent(Integer articleId) {
        Optional<ArticleContent> articleContent = articleContentRepository.findById(articleId);
        return articleContent
                .map(content -> new ResponseResult<>(HttpCodeEnum.SUCCESS, content))
                .orElse(new ResponseResult<>(HttpCodeEnum.DATA_NOT_EXIST));
    }

    /**
     * 根据id获取文章
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult getArticleById(Integer id) {
        CaArticle article = this.getById(id);
        return Optional.ofNullable(article)
                .map(o -> new ResponseResult(HttpCodeEnum.SUCCESS, o))
                .orElse(new ResponseResult(HttpCodeEnum.DATA_NOT_EXIST));
    }

    /**
     * 文章互动
     *
     * @param dto
     */
    @Override
    public void interaction(ArticleInteractionDto dto, Boolean cancel) {
        CaArticle article = this.getById(dto.getArticleId());
        int num = cancel ? -1 : 1;
        if (article == null) {
            return;
        }
        switch (dto.getType()) {
            case ArticleInteractionConstants.VIEWS:
                article.setViews(article.getViews() + num);
                break;
            case ArticleInteractionConstants.LIKES:
                article.setLikes(article.getLikes() + num);
                break;
            case ArticleInteractionConstants.COLLECTION:
                article.setCollection(article.getCollection() + num);
                break;
            case ArticleInteractionConstants.COMMENT:
                article.setComment(article.getComment() + num);
                break;
            default:
                break;
        }
        this.updateById(article);
    }

    /**
     * 获取10条推荐文章
     */
    public List<CaArticle> getRecommendArticles(int blockId) {
        return this.getBaseMapper().getArticlesByLikesLimitRandom(blockId, 10);
    }

    /**
     * 获取10条最新文章
     *
     * @param page 页码
     */
    public List<CaArticle> getLatestArticles(int blockId, int page) {
        Page<CaArticle> page1 = new Page<>(page, 10);
        page1.addOrder(OrderItem.desc("created_time"));
        LambdaQueryWrapper<CaArticle> wrapper = Wrappers.<CaArticle>lambdaQuery()
                .eq(CaArticle::getStatus, ArticleConstants.Pass_The_examination);
        if (blockId != 1) {
            wrapper.eq(CaArticle::getBlockId, blockId);
        }
        this.getBaseMapper().selectPage(page1, wrapper);
        return page1.getRecords();
    }
}
